<!--
 * @Author: your name
 * @Date: 2021-12-14 00:23:44
 * @LastEditTime: 2021-12-26 00:46:46
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \homeStayMS\src\main\resources\static\vue\MainPage\shopManage\shopManage.vue
-->


<!-- template模板语法。全部的代码都必须在template标签下面编写。-->
<template>
  <!-- 
    template模板下只能有一个根标签 这个父级元素建议写成section以便实现语义化。
    为了方便调试，默认给根标签携带id，id名默认取小驼峰命名的文件名。
  -->
  <section id="storeManage">

    <!-- 
      搜索组件
      每一个列表页都默认需要一个搜索组件。其具体的配置，props传参格式如下：
      
      搜索选择内容返回值数组
      :search-select.sync="返回值数组"
      其中，这个数组定义在data内。

      搜索栏配置数组
      :search-form-list="配置数组"

      其中、配置数组和返回值数组都在data内定义，详情看data

      组件命名：
      默认以短横杠命名，默认写成固定名称 search-bar 。否则无法识别。
     -->
    <search-bar
      ref="searchBar"
      :search-select.sync="searchSelect"
      :search-form-list="searchFormList"
    >
    </search-bar>

    <!-- 
      基本的按钮列 (目前不需要后端模仿实现)
     -->
    <section style="margin-bottom: 20px">
      <el-button
        type="primary"
        size="mini"
        @click="openAddStoreFrame(false, '')"
      >
        添加门店
      </el-button>
    </section>

    <!-- 
      表格组件
      组件命名： 短横杠 默认取名为 table-frame

      需要传递的两个参数：
      表格表列配置 tableCols为表列配置数组
      :table-cols="tableCols"

      表格数据配置 tableData为后端返回的数组
      :table-data="tableData"
    -->
    <table-frame :table-cols="tableCols" :table-data="tableData">
      <!-- 内层的template模板内容暂时不要求后端模仿复制 -->
      <template #operation="scope">
        <el-button
          type="primary"
          size="mini"
          @click="openAddStoreFrame(true, scope.row.sId)"
        >
          编辑
        </el-button>

        <el-button
          type="primary"
          size="mini"
          @click="delStoreInfo(scope.row.sId)"
        >
          删除
        </el-button>
      </template>
    </table-frame>

    <!-- 
      表格分页栏组件
      本组件除了以下配置以外，其余的均必须写死，直接复制粘贴即可
      配置分页栏换页时请求的后端接口函数，默认取名为getTableList函数
      @pagination="getTableList()"
     -->
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="pagination.pageNum"
      :limit.sync="pagination.pageSize"
      @pagination="getTableList()"
    ></pagination>

    <!-- 以下template标签内容不要求后端模仿复制粘贴 -->
    <template>
      <!-- 弹框组件 -->
      <add-edit-store-frame
        :dialogVisible.sync="isOpenAddFrame"
        :isEdit="isEditStoreInfo"
        :sId="selectedSId"
        @updateTableList="getTableList()"
      ></add-edit-store-frame>
    </template>
  </section>
</template>

<script>
// 在各个列表页中，以下三行import语句直接复制粘贴。其作用是引入公共组件。
import SearchBar from '../../common-components/SearchBar/SearchBar.vue';
import TableFrame from '../../common-components/TableFrame/TableFrame.vue';
import Pagination from '../../common-components/Pagination/Pagination.vue';

// 该语句不要求后端复制粘贴。其作用是导入同文件夹下的弹框组件。
import addEditStoreFrame from './addEditStoreFrame.vue';

// 在各个列表页中，该import语句需要复制。其作用是引入后端的接口。
import api from '../../../js/api/api.js';

/**
 * export default {}
 * vue语法格式。默认导出一个vue组件。目前每一个列表页都已经实现了此内容。
 */
export default {
  // 组件的名称 目前每一个列表页都已经实现。默认要求使用大驼峰命名。
  name: 'storeManage',

  /**
   * 当前组件的子组件。该内容默认需要直接复制粘贴。否则其他的组件均无法使用。其含义是声明注册子组件。
   * 按照这个方式复制粘贴：
   */
  // components: {
  //   SearchBar,
  //   TableFrame,
  //   Pagination,
  // },
  components: {
    SearchBar,
    TableFrame,
    Pagination,

    // 此内容不需要后端复制。因为本页面实现了弹框子组件。
    addEditStoreFrame,
  },

  /**
   * vue组件的变量定义区域
   * 必须要编写为一个函数 其格式为 data(){ return {} }
   * 定义的数据必须写在return返回值的对象内。
   */
  data() {
    return {
      /**
       * 搜索组件接收值
       * 必须需要定义此对象，否则搜索组件无法返回值。
       * 该对象默认为一个空对象。不配置任何键值对。
       * 其变量命名默认为 searchSelect
       */
      searchSelect: {
        sName: '',
      },

      /**
       * 搜索组件的配置列表
       * 必须要定义此数组，否则搜索组件无法配制出显示内容
       * 该数组有多少个对象，搜索组件就会显示出多少个内容
       */
      searchFormList: [
        /**
         * prop 必须配置的键名 键值配置想要搜索的字段名 如区域字段 region
         * type 必须配置的键名 如果需要使用输入框 则配置字符串'input'
         * label 必须配置的键名 为搜索栏的名称
         * placeholder 非必要但默认填写的键名 为输入栏的默认提示文本
         */
        {
          prop: 'sName',
          type: 'input',
          label: '门店名称',
          placeholder: '请输入门店名称',
        },

        // 接口设计成，仅有一个条件可以筛选 故注释
        // {
        //   prop: 'region',
        //   type: 'input',
        //   label: '地区',
        //   placeholder: '请输入地区',
        // },

        /**
         * 下拉框搜索栏配置
         *
         * 与上面相同的字段不赘述
         * type 如果你需要使用下拉框搜索栏，必须要写 'composite'
         * inputProp 输入栏接受值的名称 这里默认填写为 'inputContent'
         * selectProp 选择栏接受的名称 默认填写为 'searchType'
         * selectWidth 选择栏宽度 必填 填值为字符串格式的样式宽度 单位为px
         *
         * options 选项数组 选项对应的中文名即对应的字段
         * 不要求后端配置 options 数组。
         */
        // {
        //   prop: 'inputContent',
        //   type: 'composite',
        //   placeholder: '请输入',
        //   inputProp: 'inputContent',
        //   selectProp: 'searchType',
        //   selectWidth: '110px',
        //   options: [
        //     { label: '门店名称', value: 'sName' },
        //     { label: '地区', value: 'region' },
        //   ],
        // },

        {
          type: 'button',
          name: '搜索',
          btnType: 'primary',
          handle: this.search,
        },

        {
          type: 'button',
          name: '重置',
          handle: this.resetSearchFrame,
        },
      ],

      /**
       * 表格数据
       * 必须定义该变量，且必须要分页查询接口实现对该变量的赋值，否则无法实现数据显示。
       * 该数组默认定义为空数组。
       */
      tableData: [],

      /**
       * 表格表列配置数组
       * 必须定义该变量
       *
       * 配置基本思路是：配置后端列表字段名、字段对应的中文名、表列宽度
       * prop 必填键名 取值为字符串的字段 如门店编号字段 'sId'
       * slotname 写法与prop完全一样，必填字段
       * label 必填键名 表格表头的中文名
       * minWidth 最小宽度 必填键名 填值填写为字符串数字
       */
      tableCols: [
        {
          prop: 'sId',
          slotname: 'sId',
          label: '门店编号',
          minWidth: '140',
        },

        {
          prop: 'sName',
          slotname: 'sName',
          label: '门店名称',
          minWidth: '140',
        },

        {
          prop: 'region',
          slotname: 'region',
          label: '地区',
          minWidth: '140',
        },

        // 表格操作列目前不要求后端模仿配置
        {
          prop: 'operation',
          label: '操作',
          slotname: 'operation',
          fixed: 'right',
          width: '220',
        },
      ],

      /**
       * 来自后端分页查询的数据总数
       * 必须定义 且取名为total 初始值必须为数字格式的0
       * 直接复制粘贴即可
       */
      total: 0,

      /**
       * 分页栏组件内的页码控制对象
       * 必须定义 直接复制粘贴即可
       */
      pagination: {
        pageSize: 5,
        pageNum: 1,
      },

      /** 是否打开添加框？ 不要求后端复制粘贴 */
      isOpenAddFrame: false,

      /** 是否编辑门店信息？ 不是则属于新增门店信息 不要求后端复制粘贴 */
      isEditStoreInfo: false,

      /** 被选择的门店id值 不要求后端复制粘贴 */
      selectedSId: '',
    };
  },

  /**
   * 方法对象
   * vue语法格式，每一个vue组件的函数必须以键值的形式定义在此对象内。
   * 函数写法不需要写成严格的键值对形式。
   * methods:{}
   */
  methods: {
    // 搜索
    search() {
      const newPagination = { pageSize: 5, pageNum: 1 };
      Object.assign(this.pagination, newPagination);
      this.getTableList(this.searchSelect);
    },

    /** 重置搜索组件筛选项 搜索组件的筛选项表单内容 */
    async resetSearchFrame() {
      this.$refs.searchBar.resetForm();
      await this.getTableList();
    },

    /**
     * 分页查询接口 获得列表数据
     * 必须定义的函数，且取名建议为 getTableList 如果没定义，则无法获取到接口数据。
     * 该函数与后端接口紧密结合。
     */
    async getTableList(filterParam = {}) {
      let addObj = {};
      if (!!this.searchSelect.sName) {
        addObj = { sName: this.searchSelect.sName };
      } else {
        addObj = { id: localStorage.getItem('userId') };
      }

      const getData = {
        ...this.pagination,
        ...filterParam,
        ...addObj,
      };

      /**
       * 请求后端数据 该部分大部分都需要直接复制粘贴，仅有接口函数需要重新根据api的配置来取名。
       * 如： 本页面的分页查询函数是 getStoreList ，则调用api内定义的函数
       */
      await api.getStoreList(getData).then((res) => {
        if (res.status === 200) {
          const data = res.data;
          if (data.status) {
            this.tableData = data.result.content;
            this.total = data.result.total;
          }
        }
      });
    },

    /**
     * 打开门店添加弹框 该函数不要求后端实现
     * isEdit 形参为是否编辑状态
     * sId 门店的id
     */
    openAddStoreFrame(isEdit, sId) {
      // 打开门店新增与编辑弹框
      this.isOpenAddFrame = true;
      // 更改状态 不属于编辑状态 即新增
      this.isEditStoreInfo = isEdit;
      // 更新被选择的门店id值。
      this.selectedSId = sId;
    },

    /** 删除门店信息  */
    delStoreInfo(sId) {
      this.$confirm('是否要删除此门店？', '提示', {
        confirmButtonText: '确定删除',
        cancelButtonText: '取消返回',
        type: 'warning',
      })
        .then(() => {
          api.removeStoreInfo({ sId }).then(async (res) => {
            if (res.status === 200) {
              await this.getTableList();
              this.$message.success('删除成功');
            }
          });
        })
        .catch(() => {});
    },
  },

  /**
   * 生命周期函数 created 必须实现，否则页面初始化时没有数据
   * 该部分直接复制粘贴即可。
   */
  async created() {
    await this.getTableList();
  },
};
</script>

<!-- 
  样式
  vue语法：必须增加配置 scoped 否则会出现样式污染问题
  目前不推荐后端直接写样式，很容易出现混乱。
 -->
<style scoped>
.button-frame {
  margin-bottom: 20px;
}
</style>
